import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

public class RenderMachine implements Runnable {
	
	boolean verbose;
	Controller cont;	
	int boxWidth;
	int boxHeight;
	int lastBoxWidth;
	int lastBoxHeight;
	int row;
	int column;
	AtomicBoolean continueWork;
	ArrayBlockingQueue<Point> latestPoint;
	MandelbrotRender mandelbrotRenderer;
	int totalWidth;
	int totalHeight;

	public RenderMachine(Properties prop, Controller theCont, AtomicBoolean continueWork, ArrayBlockingQueue<Point> latestPoint) {
		this.verbose = prop.getProperty("verbose").equals("true");
		this.cont = theCont;
		this.boxWidth = Integer.parseInt(prop.getProperty("boxWidth"));
		this.boxHeight = Integer.parseInt(prop.getProperty("boxHeight"));
		this.lastBoxWidth = Integer.parseInt(prop.getProperty("lastBoxWidth"));
		this.lastBoxHeight = Integer.parseInt(prop.getProperty("lastBoxHeight"));
		this.row = Integer.parseInt(prop.getProperty("row"));
		this.column = Integer.parseInt(prop.getProperty("column"));
		this.totalWidth = Integer.parseInt(prop.getProperty("width"));
		this.totalHeight = Integer.parseInt(prop.getProperty("height"));
		this.continueWork = continueWork;
		this.latestPoint = latestPoint;
		this.mandelbrotRenderer = new MandelbrotRender(totalWidth, totalHeight, verbose);
	}
	
	private int getBoxHeight(int y){
		if( y == row-1){
			return lastBoxHeight;
		}
		else return boxHeight;
	}
	
	private int getBoxWidth(int x){
		if( x == column-1){
			return lastBoxWidth;			
		}
		else return boxWidth;
	}
		
	private int findBoxRow(int mouse_y){
		return (mouse_y / boxHeight);
	}

	private int findBoxColumn(int mouse_x){
		return (mouse_x / boxWidth);
	}
	
	private int findYPositionInBox(int mouse_y, int boxRow, int boxHeight){
		return mouse_y - boxRow*boxHeight;
	}
	
	private int findXPositionInBox(int mouse_x, int boxColumn, int boxWidth){
		return mouse_x - boxColumn*boxWidth;
	}
	
	@Override
	public void run() {
		while(continueWork.get()){
			/*
			try {
				Thread.sleep(10);
				cont.getMouseLocation();
				Point latest = latestPoint.get();
				latestPoint.set(null);
				if(latest == null) continue;
				System.out.println(latest);
				int boxColumn = findBoxColumn(latest.x);
				int boxRow = findBoxRow(latest.y);
				int boxWidth = getBoxWidth(boxColumn);
				int boxHeight = getBoxHeight(boxRow);	
				int xPos = findXPositionInBox(latest.x, boxColumn, boxWidth);
				int yPos = findYPositionInBox(latest.y, boxRow, boxHeight);
				RenderableBox replacementBox = new RenderableBox(boxWidth, boxHeight, verbose);
				BufferedImage img = replacementBox.getBufferedImage();
				try{
					img.setRGB(xPos, yPos, Color.WHITE.getRGB());
					cont.replaceBox(boxRow,boxColumn,img);
				}
				catch (ArrayIndexOutOfBoundsException e){
					System.out.println(latest);
					System.out.println(boxColumn + " " +  boxRow);
					System.out.println(boxWidth + " " +  boxHeight);				
					System.out.println(xPos + " " +  yPos);
				}				
				} catch (InterruptedException e) {
				//TODO Auto-generated catch block
				e.printStackTrace();
			}	*/
		//}		
		
			for(int i = 0; i<row; i++){
				for(int j = 0; j<column; j++){
					//try {				
						//Thread.sleep(100);		
						int boxWidth = getBoxWidth(j);
						int boxHeight = getBoxHeight(i);
						RenderableBox replacementBox = new RenderableBox(boxWidth, boxHeight, verbose);
						BufferedImage img = replacementBox.getBufferedImage();						
						mandelbrotRenderer.render(img,j*boxWidth,i*boxHeight);
						cont.replaceBox(i,j,img);
					//} catch (InterruptedException e) {						
					//}	
				}
			}
			
			cont.getMouseLocation();
			try {
				Point latest = latestPoint.poll(10, TimeUnit.MILLISECONDS);
				if(latest != null)
					mandelbrotRenderer.updateZoom(latest);
			} catch (InterruptedException e) {				
			}		
			
		}
		System.out.println(this.getClass().getName() + " is exiting...");
	}

}
